package main

import (
	"time"

	mgo "gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

type DBOperation struct {
	session  *mgo.Session
	dbName   string
	errorMap *ErrorMap
}

const (
	CollectionCustomers      string = "customers"
	CollectionCompanies      string = "companies"
	CollectionTeams          string = "teams"
	CollectionLoginHistories string = "loginhistories"
)

const TokenExpire int64 = 24 * 60 * 60

func NewDBOperation(cfg *Config) (*DBOperation, error) {
	zLog(nil, "数据库连接::", cfg.DBUrl, " 开始")
	session, err := mgo.Dial(cfg.DBUrl)
	if err != nil {
		zLog(nil, "数据库连接失败::", err.Error())
		return nil, err
	}
	if cfg.DBUser != "" && cfg.DBPwd != "" {
		err = session.Login(&mgo.Credential{
			Username: cfg.DBUser,
			Password: cfg.DBPwd,
		})
		if err != nil {
			zLog(nil, "数据库登录失败::", err.Error())
			return nil, err
		}
	}
	//session.SetMode(mgo.Eventual) //该模式最大的特点就是不会缓存连接
	session.SetPoolLimit(100)

	dbo := DBOperation{session, cfg.DBName, NewErrorMap()}

	return &dbo, nil
}

func (p *DBOperation) Close() {
	p.session.Close()
}

type CustomerT struct {
	CompanyId   int `bson:"cid"`
	CompanyName string
	TeamId      string `bson:"tid"`
	TeamName    string
	UserId      bson.ObjectId `bson:"_id"`
	Username    string        `bson:"uname"`
	Usertype    int           `bson:"utype"`
	Phone       string        `bson:"phone"`
	NoDevice    bool          `bson:"nodevice"`
	NoSite      bool          `bson:"nosite"`
	WxId        string        `bson:"wxid"`
	WxName      string        `bson:"wxname"`
	WxHead      string        `bson:"wxheadimgurl"`
	Threshold1  int           `bson:"tpdt1"`
	Threshold2  int           `bson:"tpdt2"`
}

func (p *DBOperation) Login(user, password string) (errCode int, customer *CustomerT) {
	s := p.session.Copy()
	defer s.Close()

	c := s.DB(p.dbName).C(CollectionCustomers)
	var e CustomerT

	err := c.Find(bson.M{"user": user, "pass": password}).Select(bson.M{"_id": 1, "cid": 1, "tid": 1, "utype": 1, "uname": 1, "phone": 1,
		"nodevice": 1, "nosite": 1, "wxid": 1, "wxname": 1, "wxheadimgurl": 1, "tpdt1": 1, "tpdt2": 1}).One(&e)
	if err != nil {
		zLog(nil, "Login Find tableName::", CollectionCustomers, " error::", err.Error())
		return 1001, nil
	}
	zLog(nil, "Login Find tableName::", CollectionCustomers, " rsp::", e)
	e.CompanyName = p.companyName(e.CompanyId)
	if e.TeamId != "" {
		e.TeamName = p.teamName(e.TeamId)
	}

	return 0, &e
}

type UserTokenT struct {
	TokenExpire int64 `bson:"tokenexpire"`
}

func (p *DBOperation) checkAccessToken(userid string, token string) bool {
	s := p.session.Copy()
	defer s.Close()

	oi := bson.ObjectIdHex(userid)
	c := s.DB(p.dbName).C(CollectionCustomers)
	var ut UserTokenT

	err := c.Find(bson.M{"_id": oi, "token": token}).Select(bson.M{"tokenexpire": 1}).One(&ut)
	if err != nil {
		return false
	}

	if time.Now().Unix()-ut.TokenExpire > TokenExpire {
		return false
	}
	return true
}

// 保存登录纪录
func (p *DBOperation) saveLoginHistory(lh *LoginHistoryT) {
	s := p.session.Copy()
	defer s.Close()

	s.DB(p.dbName).C(CollectionLoginHistories).Insert(lh)
}

func (p *DBOperation) companyName(cid int) string {
	s := p.session.Copy()
	defer s.Close()

	c := s.DB(p.dbName).C(CollectionCompanies)
	var res map[string]string

	err := c.Find(bson.M{"cid": cid}).Select(bson.M{"_id": 0, "name": 1}).One(&res)
	if err != nil {
		return ""
	}
	return res["name"]
}

func (p *DBOperation) teamName(tid string) string {
	if bson.IsObjectIdHex(tid) {
		s := p.session.Copy()
		defer s.Close()

		c := s.DB(p.dbName).C(CollectionTeams)
		var res map[string]string
		objId := bson.ObjectIdHex(tid)

		err := c.Find(bson.M{"_id": objId}).Select(bson.M{"_id": 0, "name": 1}).One(&res)
		if err != nil {
			return ""
		}
		return res["name"]
	} else {
		return ""
	}
}

func (p *DBOperation) customerList(tid string, key string, pageno int) string {
	s := p.session.Copy()
	defer s.Close()
	c := s.DB(p.dbName).C(CollectionCustomers)
	q1 := bson.M{"user": bson.M{"$in": []string{key}}}
	//q2 := bson.M{"uname": bson.M{"$in": []string{key}}}
	//result := c.Find(bson.M{"$or": []bson.M{q1, q2}})
	result := c.Find(q1)
	count, _ := result.Count()
	//count, _ := c.Count()
	print(count)
	return ""
}
